<template>
  <div class="page-mark-left">
    <Tabs value="basicComponent">
      <TabPane label="基础组件" name="basicComponent">
        <!-- 常用组件 -->
        <template v-for="item of getIconList(0)">
          <dl class="component-item" :key="item.type" v-if="item.common">
            <dt @mousedown="onStart($event,item)">
              <i :class="['ivu-icon', item.icon]" v-if="item.icon.indexOf('ivu-icon')>-1"></i>
              <i :class="['iconfont', item.icon]" v-else></i>
              <span>{{item.text}}</span>
            </dt>
          </dl>
        </template>

        <Collapse simple class="more-component">
          <Panel name="more">
            更多
            <template v-for="item of getIconList(0)" slot="content">
              <dl class="component-item" :key="item.type" v-if="!item.common">
                <dt @mousedown="onStart($event,item)">
                  <i :class="['ivu-icon', item.icon]" v-if="item.icon.indexOf('ivu-icon')>-1"></i>
                  <i :class="['iconfont', item.icon]" v-else></i>
                  <span>{{item.text}}</span>
                </dt>
              </dl>
            </template>
          </Panel>
        </Collapse>
      </TabPane>
      <TabPane label="高级组件" name="seniorComponent">
        <dl class="component-item" v-for="item of getIconList(1)" :key="item.type">
          <dt @mousedown="onStart($event,item)">
            <i :class="['ivu-icon', item.icon]" v-if="item.icon.indexOf('ivu-icon')>-1"></i>
            <i :class="['iconfont', item.icon]" v-else></i>
            <span>{{item.text}}</span>
          </dt>
        </dl>
      </TabPane>
    </Tabs>
  </div>
</template>

<script>
import { iconList } from './config/icon';
import { navCollapsedWidth, navExpandWidth, defaultTopHeight, leftWidth, rightWidth, componentHeight, componentHalfHeight } from './config/code';
import { componentsList } from './config/component';
import { mapState, mapMutations } from 'vuex';
import { deepCopy } from 'assets/scripts/common';
import bus from 'assets/scripts/bus';

export default {
  computed: {
    ...mapState({
      activeCom: state => state.mark.activeCom,
      components: state => state.mark.components,
      layout: state => state.mark.layout,
      dragInfo: state => state.mark.dragInfo,
      navCollapsed: state => state.app.navCollapsed
    })
  },
  data () {
    return {
      componentsList,
      iconList,
      posX: 0,
      posY: 0,
      dragFlag: false
    };
  },
  methods: {
    ...mapMutations(['addComponents', 'setActiveCom', 'addLayout', 'setDragInfo', 'setDragShow']),

    // 0基础组件，1高级组件
    getIconList (type) {
      return this.iconList.filter(item => {
        return item.componentType === type;
      })
    },

    // 新建组件
    createItem () {
      let { componentData, layoutData } = this.dragInfo;

      // 加到位置中
      this.addLayout(layoutData);
      componentData.location = layoutData;

      // 加到组件中
      this.addComponents(componentData);

      // 激活当前组件的设置
      // console.log(componentData, '当前激活组件')
      this.setActiveCom(componentData);

      // 激活Middle组件的激活样式
      bus.$emit('setMiddleActiveStyle', this.layout.length - 1);
    },

    // 鼠标点击组件mousedown
    onStart (event, item) {
      let obj = Object.assign({}, item);

      // 获取点击的位置
      this.posX = this.navCollapsed ? navCollapsedWidth : navExpandWidth;
      this.posY = defaultTopHeight;

      // 第一次出现的位置
      obj.x = event.pageX - this.posX;
      obj.y = event.pageY - this.posY;

      // 生成点击的数据
      let newData = deepCopy(componentsList.default);
      let comData;
      newData.id = new Date().getTime();
      newData.key = `key${newData.id}`;

      // 生成对应的组件数据
      if (componentsList[item.type]) {
        comData = Object.assign(
          {},
          newData,
          deepCopy(componentsList[item.type])
        );
      } else {
        comData = Object.assign({}, newData, {
          name: `${item.type}Item`
        });
      }
      obj.componentData = comData;

      // 获取对应的位置
      let layoutObj = {
        x: 0, // 标识栅格元素位于第几列，需为自然数。
        y: 0, // 标识栅格元素位于第几行，需为自然数。
        w: 12, // 标识栅格元素的初始宽度，值为colWidth的倍数。
        h: 1, // 高度，30的倍数
        i: 0 // 索引
      };

      // 默认位置信息的拓展
      layoutObj = Object.assign(
        {},
        layoutObj,
        deepCopy(componentsList[item.type].location)
      );

      // 添加位置的判断
      if (this.layout.length > 0) {
        layoutObj.i = this.layout.length;

        let lastLayoutY = this.layout[this.layout.length - 1].y;
        layoutObj.y = lastLayoutY + 1;
      }
      obj.layoutData = layoutObj;

      // 显示拖拽的组件
      this.setDragInfo(obj);
      this.setDragShow(true);

      // 表示开始拖拽
      this.dragFlag = true;
      document.body.style.userSelect = 'none';
      document.addEventListener('mousemove', this.move);
      document.addEventListener('mouseup', this.onEnd);
    },

    // 移动过程中更新位置-mousemove
    move (event) {
      if (this.dragFlag) {
        let info = this.dragInfo;
        info.x = event.pageX - this.posX;
        info.y = event.pageY - this.posY;
        this.setDragInfo(info);
      }
    },

    // 松开鼠标，判断位置是否新增组件-mouseup
    onEnd (event) {
      event.stopPropagation()
      this.dragFlag = false;

      // 判断是不是在中间区域
      let x1 = this.posX + leftWidth;
      let x2 = document.body.clientWidth - rightWidth;
      let y1 = this.posY + componentHalfHeight;
      let cx = event.pageX;
      let cy = event.pageY;

      // 在中间区域内
      if (cx >= x1 && cx <= x2 && cy >= y1) {
        // 对组件布局的判断，x和y的判断
        let middleWidth = x2 - x1;
        let oneWidth = middleWidth / 24;
        let oneHeight = componentHeight + 10;

        let sx = cx - x1 - componentHalfHeight;
        this.dragInfo.layoutData.x = Math.floor(sx / oneWidth)

        // 需要获取中间面板滚动条的位置
        bus.$emit('getMiddleContentScroll');
        let sTop = sessionStorage.middleScrollTop ? Number(sessionStorage.middleScrollTop) : 0;

        let sy = cy - y1 + sTop;
        this.dragInfo.layoutData.y = Math.floor(sy / oneHeight)

        let { x, y } = this.dragInfo.layoutData;
        if (x < 0) {
          this.dragInfo.layoutData.x = 0
        }
        if (y < 0) {
          this.dragInfo.layoutData.y = 0
        }
        // 新建组件
        this.createItem();
      }

      // 事件解绑
      document.body.style.userSelect = '';
      document.removeEventListener('mousemove', this.move);
      document.removeEventListener('mouseup', this.onEnd);
      this.setDragShow(false);
    }
  }
};
</script>

<style rel="stylesheet/less" lang="less" scoped>
@import '../../assets/theme/themeBlue.less';
.page-mark-left {
  width: 200px;
  position: absolute;
  top: 50px;
  left: 0;
  bottom: 0;
  background: #fff;
  overflow-y: auto;
  .component-item {
    display: inline-block;
    width: 80px;
    margin-left: 12px;
    margin-bottom: 14px;
    dt {
      position: relative;
      display: inline-block;
      width: 100%;
      height: 30px;
      line-height: 30px;
      text-align: center;
      border-radius: 4px;
      border: @primary 1px solid;
      color: @primary;
      transition: border-color 0.3s, color 0.3s;
      transition-timing-function: cubic-bezier(0.2, 1, 0.3, 1);
      overflow: hidden;
      cursor: move;
      .ivu-icon {
        font-size: 16px;
        position: relative;
        top: -2px;
      }
      &:before {
        content: '';
        position: absolute;
        top: 0;
        left: 0;
        width: 150%;
        height: 100%;
        background-color: #142e4e;
        z-index: -1;
        transform-origin: 0% 100%;
        opacity: 0;
        transform: rotate3d(0, 0, 1, -45deg) translate3d(0, -3em, 0);
        transition: transform 0.3s, opacity 0.3s, background-color 0.3s;
      }
    }
    dd {
      text-align: center;
      width: 100%;
      margin-top: 4px;
    }
    &:hover {
      dt {
        background: @primary;
        color: #fff;
        &::before {
          opacity: 1;
          background-color: @primary;
          transform: rotate3d(0, 0, 1, 0deg);
          transition-timing-function: cubic-bezier(0.2, 1, 0.3, 1);
        }
      }
    }
  }
}
</style>

<style lang="less">
.page-mark-left {
  .ivu-tabs-nav .ivu-tabs-tab {
    font-size: 12px;
  }
  .more-component {
    .ivu-collapse-content {
      padding: 0;
    }
  }
}
</style>
